package com.chenyuhan.myview.testview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;

import com.chenyuhan.myview.R;

import java.util.HashSet;
import java.util.Random;
import java.util.Set;

import static android.view.View.MeasureSpec.AT_MOST;
import static android.view.View.MeasureSpec.EXACTLY;

/**
 * Created by Administrator on 2017/6/26 0026.
 */

public class TestTextView extends View {
    private final String TAG = TestTextView.class.getSimpleName();
    /**
     * 文本
     */
    private String mText;
    /**
     * 文本颜色
     */
    private int mTextColor;
    /**
     * 文本大小
     */
    private int mTextSize;

    /**
     * 绘制时控制文本绘制的范围
     */
    private Paint mPaint;
    private Rect mBound;

    public TestTextView(Context context) {
        this(context, null);
    }

    public TestTextView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TestTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        /**
         * 获得我们所定义的自定义样式属性
         */
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TestTextView, defStyleAttr, 0);
        for (int i = 0; i < typedArray.getIndexCount(); i++) {
            int attr = typedArray.getIndex(i);
            switch (attr) {
                case R.styleable.TestTextView_textOne:
                    mText = typedArray.getString(attr);
                    break;
                case R.styleable.TestTextView_textColorOne:
                    // 默认颜色设置为黑色
                    mTextColor = typedArray.getColor(attr, Color.BLACK);
                    break;
                case R.styleable.TestTextView_textSizeOne:
                    // 默认设置为16sp，TypeValue也可以把sp转化为px
                    mTextSize = typedArray.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
                    break;
            }
        }
        typedArray.recycle();
        /**
         * 获得绘制文本的宽和高
         */
        mPaint = new Paint();
        mPaint.setTextSize(mTextSize);
        //计算文字所在矩形，可以得到文字的宽高
        mBound = new Rect();
        mPaint.getTextBounds(mText, 0, mText.length(), mBound);
        this.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                mText = randomText();
                //界面刷新
                //invalidate() 方法在 UI 线程中调用，重绘当前 UI。
                //postInvalidate() 方法在非 UI 线程中也可以调用，通知 UI 线程重绘。（发送了一个msg，最终也是调用view的invalidate()方法）
                //之后会调用onDraw()
                invalidate();
            }
        });
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //该view在父布局只有一层的情况下onMeasure会被调用四次，多层嵌套会更多，每多嵌套一层就多一倍
        //官方文档解释为：
        //父视图可能在它的子视图上调用一次以上的measure(int,int)方法。
        // 例如，父视图可以使用unspecified dimensions来将它的每个子视图都测量一次来算出它们到底需要多大尺寸，
        // 如果所有这些子视图没被限制的尺寸的和太大或太小，那么它会用精确数值再次调用measure()
        // （也就是说，如果子视图不满意它们获得的区域大小，那么父视图将会干涉并设置第二次测量规则）。
        Log.i(TAG, "onMeasure: ");
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        //最终宽高
        int width = 0;
        int hegiht = 0;
        mPaint.setTextSize(mTextSize);
        mPaint.getTextBounds(mText, 0, mText.length(), mBound);
        //重写之前先了解MeasureSpec的specMode,一共三种类型：
        //EXACTLY：一般是设置了明确的值或者是MATCH_PARENT
        //AT_MOST：表示子布局限制在一个最大值内，一般为WARP_CONTENT
        //UNSPECIFIED：表示子布局想要多大就多大，很少使用
        switch (widthMode) {
            case EXACTLY:
                width = widthSize;
//                Log.i(TAG, "widthMode: EXACTLY " + width);
                break;
            case AT_MOST:
                float textWidth = mBound.width();
                int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight());
                width = desired;
//                Log.i(TAG, "widthMode: AT_MOST " + width);
                break;
        }
        switch (heightMode) {
            case EXACTLY:
                hegiht = heightSize;
//                Log.i(TAG, "heightMode: EXACTLY " + hegiht);
                break;
            case AT_MOST:
                float textHeight = mBound.height();
                int desired = (int) (getPaddingTop() + textHeight + getPaddingBottom());
                hegiht = desired;
//                Log.i(TAG, "heightMode: AT_MOST " + hegiht);
                break;
        }
        setMeasuredDimension(width, hegiht);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        Log.i(TAG, "onLayout: ");
    }

    @Override
    protected void onDraw(Canvas canvas) {
        mPaint.setColor(getResources().getColor(R.color.colorPrimary));
        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);

        mPaint.setColor(mTextColor);
        mPaint.setTextSize(mTextSize);
        //canvas.drawText(text, x, y, paint)
        //第一个参数是我们需要绘制的文本，第四个参数是我们的画笔，这两个不用多说，
        // 主要是第二和第三个参数的含义，这两个参数在不同的情况下的值还是不一样的，
        // x默认是这个字符串的左边在屏幕的位置，如果设置了paint.setTextAlign(Paint.Align.CENTER);那就是字符的中心，
        // y是指定这个字符baseline在屏幕上的位置
        canvas.drawText(mText, getWidth() / 2 - mBound.right / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
        //Log.i(TAG, "onDraw:mBound.width() " + mBound.width());
        //Log.i(TAG, "onDraw:mBound.right " + mBound.right);
        //Log.i(TAG, "onDraw:mBound.left " + mBound.left);
        //Log.i(TAG, "onDraw:mBound.height() " + mBound.height());
        //Log.i(TAG, "onDraw:mBound.top " + mBound.top);
        //Log.i(TAG, "onDraw:mBound.bottom " + mBound.bottom);
        //mBound,width()=mBound.right-mBound.left，若left不为0,则会出现文本靠右的情况
    }

    private String randomText() {
        Random random = new Random();
        Set<Integer> set = new HashSet<Integer>();
        while (set.size() < 4) {
            int randomInt = random.nextInt(10);
            set.add(randomInt);
        }
        StringBuffer sb = new StringBuffer();
        for (Integer i : set) {
            sb.append("" + i);
        }

        return sb.toString();
    }

}
